/**
@file

@brief

@author
	GengYong
@revision
	2005/11/15 * Created by GengYong.
*/


#ifndef SAF_HEADER_FILE_STDUTILITY_H
#define SAF_HEADER_FILE_STDUTILITY_H

#include <string>
namespace Util
{
	//######################## standard method ############################
	enum CompareResult { less = -1, equal = 0, great = 1 };
	
	inline CompareResult Util_CompareString(const char * src, const char * cmp)
	{
		return CompareResult(strcmp(src, cmp));
	}

	inline CompareResult Util_CompareStringIC(const char * src, const char * cmp)
	{
#if defined(WIN32)
		return CompareResult(_stricmp(src, cmp));
#elif defined(LINUX)
		return CompareResult(strcasecmp(src, cmp));
#elif defined(UNIX)
		return CompareResult(strcasecmp(src, cmp));
#elif defined(BSD)
		return CompareResult(strcasecmp(src, cmp));
#else
	#error Unknown Platfrom. Please check the envirment setting.
#endif
	}

	inline CompareResult Util_CompareMemory(const void * src, void * cmp, unsigned long size)
	{
		return CompareResult(memcmp(src, cmp, size));
	}
	
	inline void * Util_MemoryCopy(void * dst, const void * src, unsigned long size)
	{
		return memcpy(dst, src, size);
	}

	inline unsigned long Util_StringLength(const char * str)
	{
		return (unsigned long)(strlen(str));
	}

	//######################## string poll method ##########################
	inline char * Util_AllocString(const char * src)
	{
		unsigned long length = Util::Util_StringLength(src) + 1;
		char * newstr = new char[length];
		if (newstr != NULL)
		{
			Util::Util_MemoryCopy(newstr, src, length);
		}
		return newstr;
	}

	inline void Util_FreeString(const char * str)
	{
		delete[] str;
	}

	//################### Cross Platform supported method ##################

	//=========================== WIN32 Platform ===========================
#if defined(WIN32)
#define PLATFORMSTRING  "WIN32"

#include <windows.h>

	class DynamicLibrary
	{
	public:
		DynamicLibrary(const char * filename)
		{
			m_handle = LoadLibraryExA(filename, NULL, 0);
			return;
		}
		~DynamicLibrary()
		{
			if (IsLoaded()) FreeLibrary(m_handle);
			return;
		}
	public:
		bool	IsLoaded()
		{
			return (m_handle != 0);
		}
		void *  GetProcAddr(const char * procname)
		{
			if (IsLoaded())
			{
				return GetProcAddress(m_handle, procname);
			}
			else
			{
				return 0;
			}
		}
	private:
		HMODULE	m_handle;
	};

	//-----------------------------------------------------------------------
	inline void Util_WaitTime(unsigned long time)
	{
		Sleep(time);
	}
		
	//=======================================================================

	//-----------------------------------------------------------------------
	inline unsigned long Util_GetTime()
	{
		return GetTickCount();
	}
	//=======================================================================



	//=========================== LINUX Platform ============================
#elif defined(LINUX)
#define PLATFORMSTRING "LINUX"

#include <dlfcn.h>
#include <unistd.h>

	class DynamicLibrary
	{
	public:
		DynamicLibrary(const char * filename):m_handle(0)
		{
			m_handle = dlopen(filename, RTLD_LAZY);
			const char * errcode;
			if ((errcode = dlerror()) != 0)
			{
				printf("load so failed. errcode: %s\n", errcode);
				m_handle = 0;
			}
			return;
		}
		~DynamicLibrary()
		{
			if (IsLoaded()) dlclose(m_handle);
			return;
		}
	public:
		bool	IsLoaded()
		{
			return (m_handle != 0);
		}
		void *  GetProcAddr(const char * procname)
		{
			if (IsLoaded())
			{
				return dlsym(m_handle, procname);
			}
			return 0;
		}
	private:
		void *	m_handle;
	};

	//-----------------------------------------------------------------------
	inline void Util_WaitTime(unsigned long time)
	{
		usleep(time * 1000);
	}
	//=======================================================================

	//-----------------------------------------------------------------------
	extern unsigned long CPU_FREQUENCY_KHZ;
	//=======================================================================

	//-----------------------------------------------------------------------
	inline unsigned long Util_GetTime()
	{
		unsigned long cycle;
		__asm__ __volatile__ ("movl %0, %%ecx": :"m"(CPU_FREQUENCY_KHZ));		
		__asm__ __volatile__ ("rdtsc");
		__asm__ __volatile__ ("div %%ecx":"=a"(cycle));
		return cycle;		
	}
	//=======================================================================


	//=========================== UNIX Platform =============================
#elif defined(UNIX)
#define PLATFORMSTRING  "UNIX"

#error Unix Platform not supported now.
	//=======================================================================




	//============================ BSD Platform =============================
#elif defined(BSD)
#define PLATFORMSTRING	"BSD"

#error BSD Platform not supported now.
	//=======================================================================




	//========================= UNKNOWN Platfrom ============================
#else
#define PLATFORMSTRING	"UNKNOWN"

#error Unknown Platform. Please check the envirment setting.
	//=======================================================================
#endif

	inline bool Util_SupportedPlatfrom(const char * str)
	{
		if (Util_CompareStringIC(str, PLATFORMSTRING) == equal)
		{
			return true;
		}
		return false;
	}

#undef PLATFORMSTRING
}

#endif	//#ifndef SAF_HEADER_FILE_STDUTILITY_H

